////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file   CollabRCBot\Gene.h
///
/// @brief  Defines the Gene interface from which concrete Genes are constructed
////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once
#include "Diff.h"

namespace CollabRC
{
    namespace Bot 
    {
        namespace AI
        {
            /**
             * @brief Abstract representation of a gene which represents a single computational
             * element in identifying vandal-like behavior.
             *
             * Genes can be crossed with other genes or mutate. Crossing a gene with another
             * like gene results in a cross of the algorithms associated with those genes.
             * Mutating a gene results in a mutation of the algorithm associated with that gene
             * or in the gene itself changing to another gene (though this should be more rare).
             *
             * This interface represents an abstract gene. The implementation details of
             * mutation and cross-breeding are left to the genes in question and are intentionally
             * partially undefined in an effort to allow the genetic model to adapt
             * without affecting the organism implementation.
             * @version $Id$
             * @author Matthew P. Del Buono
             */
            class Gene
            {
            public:
                /**
                 * @brief Performs a test on the specified diff using the gene's
                 * alleles for determination of vandalism.
                 *
                 * The result should be on the interval [0, 1], with 0 specifying
                 * "not vandalism" and 1 specifying "vandalism". Higher values should
                 * indicate a higher likelihood of vandalism, and lower values should
                 * indicate a lower likelihood of vandalism.
                 *
                 * Genes specifying values outside of the interval of [0, 1] are acceptable,
                 * but not recommended, as they can influence results in a manner that
                 * was unexpected by the organism and impair the ability of the organism
                 * to accept mutations.
                 *
                 * @param diff the diff which should be tested
                 */
                virtual float Test(const Diff& diff) const = 0;

                /**
                 * @brief Produces a new Gene object which is spawned from this Gene
                 * and another Gene.
                 * 
                 * This Gene and the supplied Gene are parents of the newly-formed Gene.
                 * The formation of the new Gene is not specified directly, but should
                 * generally be one of the two parent genes or a cross between the two 
                 * genes which is logically a compromise between the two parent genes.
                 *
                 * The newly allocated Gene object is created on the heap. It is the
                 * responsibility of the caller to track this object and free it
                 * when it is no longer needed.
                 * 
                 * @param gene the second parent Gene object
                 * @return a newly allocated Gene object spawned from the specified parents
                 */
                virtual Gene* Cross(const Gene& gene) const = 0;

                /**
                 * @brief Performs a genetic mutation upon this Gene object, producing
                 * a new Gene which is similar to, but different from this Gene.
                 *
                 * The newly created Gene object should have small but meaningful random
                 * modifications done to the gene in an attempt to improve the system.
                 * @return the mutated Gene
                 */
                virtual Gene* Mutate() const = 0;
                inline virtual ~Gene(void) { };
            };
        }
    }
}
